/*
 * Copyright (c) 2025 Huawei Device, Inc. Ltd. and <马弓手>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "LocalNotification.h"
#include "CordovaViewController.h"
#include "cJSON.h"

REGISTER_PLUGIN_CLASS(LocalNotification)
bool LocalNotification::execute(const string&  action, cJSON* args, CallbackContext cbc)
{
    if(action == "launch") {
        launch(cbc);
    }
    
    if(action == "ready") {
        deviceready();
    }
    
    if(action == "createChannel") {
        m_cbc = cbc;
        if(cJSON_GetArraySize(args)> 0) {
            cJSON* pJson = cJSON_GetArrayItem(args, 0);
            if(pJson->type == cJSON_Object) {
                char* pOption = cJSON_Print(pJson);
                executeArkTs("/pages/LocalNotification", 0, pOption, "LocalNotification", cbc);
                free(pOption);
            }
        }
    }
    
    if(action == "deleteChannel") {
        m_cbc = cbc;
        if(cJSON_GetArraySize(args)> 0) {
            cJSON* pJson = cJSON_GetArrayItem(args, 0);
            if(pJson->type == cJSON_String) {
                char* pOption = pJson->valuestring;
                executeArkTs("/pages/LocalNotification", 1, pOption, "LocalNotification", cbc);
            }
        }
    }
    
    if(action == "hasPermission") {
        m_cbc = cbc;
        executeArkTs("/pages/LocalNotification", 2, "", "LocalNotification", cbc);
    }
    
    if(action == "requestPermission" || action == "request") {
        m_cbc = cbc;
        executeArkTs("/pages/LocalNotification", 3, "", "LocalNotification", cbc);
    }
    
    if(action == "actions") {
        m_cbc = cbc;
        char* pStr = cJSON_Print(args);
        executeArkTs("/pages/LocalNotification", 4, pStr, "LocalNotification", cbc);
        free(pStr);
    }
    
    if(action == "schedule") {
        m_cbc = cbc;
        if(cJSON_GetArraySize(args)> 0) {
            cJSON* pJson = cJSON_GetArrayItem(args, 0);
            if(pJson->type == cJSON_Object || pJson->type == cJSON_Array) {
                char* pOption = cJSON_Print(pJson);
                executeArkTs("/pages/LocalNotification", 5, pOption, "LocalNotification", cbc);
                free(pOption);
            }
        }
    }
    
    if(action == "update") {
        m_cbc = cbc;
        if(cJSON_GetArraySize(args)> 0) {
            cJSON* pJson = cJSON_GetArrayItem(args, 0);
            if(pJson->type == cJSON_Object || pJson->type == cJSON_Array) {
                char* pOption = cJSON_Print(pJson);
                executeArkTs("/pages/LocalNotification", 6, pOption, "LocalNotification", cbc);
                free(pOption);
            }
        }
    }
    
    if(action == "cancel" || action == "clear") {
        m_cbc = cbc;
        if(cJSON_GetArraySize(args)> 0) {
            cJSON* pJson = cJSON_GetArrayItem(args, 0);
            if(pJson->type == cJSON_Array || pJson->type == cJSON_Number) {
                char* pOption = cJSON_Print(pJson);
                executeArkTs("/pages/LocalNotification", 7, pOption, "LocalNotification", cbc);
                free(pOption);
            }
        }
    }
    
    if(action == "cancelAll" || action == "clearAll") {
        m_cbc = cbc;
        executeArkTs("/pages/LocalNotification", 8, "", "LocalNotification", cbc);
    }
    
    if(action == "type") {
        m_cbc = cbc;
        if(cJSON_GetArraySize(args)> 0) {
            cJSON* pJson = cJSON_GetArrayItem(args, 0);
            if(pJson->type == cJSON_Number) {
                char* pOption = cJSON_Print(pJson);
                executeArkTs("/pages/LocalNotification", 9, pOption, "LocalNotification", cbc);
                free(pOption);
            }
        }
    }
    
    if(action == "ids") {
        m_cbc = cbc;
        executeArkTs("/pages/LocalNotification", 10, "", "LocalNotification", cbc);
    }
    
    if(action == "notification") {
        m_cbc = cbc;
        if(cJSON_GetArraySize(args)> 0) {
            cJSON* pJson = cJSON_GetArrayItem(args, 0);
            if(pJson->type == cJSON_Number) {
                char* pOption = cJSON_Print(pJson);
                executeArkTs("/pages/LocalNotification", 11, pOption, "LocalNotification", cbc);
                free(pOption);
            }
        }
    }
    
    if(action == "notifications") {
        m_cbc = cbc;
       if(cJSON_GetArraySize(args)> 1) {
            cJSON* pJson = cJSON_GetArrayItem(args, 1);
            if(pJson->type == cJSON_Array) {
                char* pOption = cJSON_Print(pJson);
                executeArkTs("/pages/LocalNotification", 12, pOption, "LocalNotification", cbc);
                free(pOption);
            }
        }
    }
    
    if(action == "canScheduleExactAlarms") {
       cbc.success("true");
    }
    
    if(action == "openNotificationSettings") {
        m_cbc = cbc;
        executeArkTs("/pages/LocalNotification", 13, "", "LocalNotification", cbc);
    }
    
    if(action == "openAlarmSettings") {
        cbc.error("Error:Not Supported");
    }
    
    if(action == "getUnusedAppRestrictionsStatus") {
       cbc.success(0);
    }
    
    if(action == "openManageUnusedAppRestrictions") {
       cbc.success(0);
    }
    
    if(action == "onArKTsResult") {
        return onArKTsResult(args);
    }
    return true;
}

void LocalNotification::launch(CallbackContext cbc)
{
    if(!Application::g_strNotificationBeforeInit.empty()) {
        cJSON* pAllJson = cJSON_Parse(Application::g_strPushInfoBeforeInit.c_str());
        if(pAllJson->type == cJSON_Array) {
            cJSON* pJson = cJSON_GetArrayItem(pAllJson, 0);
            int nId = 0;
            cJSON* pJsonId = cJSON_GetObjectItem(pJson, "id");
            if(pJsonId != nullptr) {
                nId = pJsonId->valueint;
            }
            string strAction = "";
            cJSON* pJsonAction = cJSON_GetObjectItem(pJson, "action");
            if(pJsonAction != nullptr) {
                strAction = pJsonAction->valuestring;
            }
            cbc.success(pJson);
        }
        cJSON_Delete(pAllJson);
    }
}

void LocalNotification::deviceready()
{
    m_isDeviceready = true;
    if(!Application::g_strNotificationBeforeInit.empty()) {
        cJSON* pAllJson = cJSON_Parse(Application::g_strPushInfoBeforeInit.c_str());
        if(pAllJson->type == cJSON_Array) {
            int nCount = cJSON_GetArraySize(pAllJson);
            for(int i=0; i<nCount; i++) {
                cJSON* pJson = cJSON_GetArrayItem(pAllJson, 0);
                fireEvent("","", pJson);
            }
        }
        cJSON_Delete(pAllJson);
    }
}

void LocalNotification::fireEvent(const string& strEvent, const string& strArg, cJSON* pJson)
{
    if(pJson != nullptr) {
        cJSON_AddStringToObject(pJson, "event", strEvent.c_str());
        if(m_isInForeground) {
            cJSON_AddTrueToObject(pJson, "foreground");
        } else {
            cJSON_AddFalseToObject(pJson, "foreground");
        }
        if(m_isDeviceready) {
            cJSON_AddFalseToObject(pJson, "queued");
        } else {
            cJSON_AddTrueToObject(pJson, "queued");
        }
    }
    char* pStr = cJSON_Print(pJson);
    string strJsCode = "cordova.plugins.notification.local.fireEvent('";
    strJsCode += strEvent;
    strJsCode += "',";
    strJsCode += strArg.empty()?"":strArg+",";
    strJsCode += pStr;
    strJsCode += ")";
    sendJavascript(strJsCode);
    free(pStr);
}
void LocalNotification::sendJavascript(const string & strJsCode)
{
    ((CordovaViewController*)Application::g_cordovaViewController)->addJavaScript(m_cbc.getWebTag(), strJsCode);
}

bool LocalNotification::onArKTsResult(cJSON* args)
{
    string content = cJSON_GetObjectItem(args, "content")->valuestring;
    cJSON* json = cJSON_GetObjectItem(args, "result");
    if(content == "createChannel") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                if(result == "true") {
                    m_cbc.success();
                } else {
                    m_cbc.error(result);
                }
            } 
        }
    }
    
    if(content == "deleteChannel") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                if(result == "true") {
                    m_cbc.success();
                } else {
                    m_cbc.error(result);
                }
            } 
        }
    }
    
    if(content == "hasPermission") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                if(result == "true") {
                    PluginResult pluginResult(PluginResult::Status::OK, true);
                    m_cbc.sendPluginResult(pluginResult);
                } else {
                     PluginResult pluginResult(PluginResult::Status::OK, false);
                    m_cbc.sendPluginResult(pluginResult);
                }
            } 
        }
    }
    
    if(content == "requestPermission") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                if(result == "true") {
                    PluginResult pluginResult(PluginResult::Status::OK, true);
                    m_cbc.sendPluginResult(pluginResult);
                } else {
                     PluginResult pluginResult(PluginResult::Status::OK, false);
                    m_cbc.sendPluginResult(pluginResult);
                }
            } 
        }
    }
    if(content == "actions") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
               string result = cJSON_GetArrayItem(json, 0)->valuestring;
                if(result == "true") {
                    PluginResult pluginResult(PluginResult::Status::OK, true);
                    m_cbc.sendPluginResult(pluginResult);
                } else {
                     PluginResult pluginResult(PluginResult::Status::OK, false);
                    m_cbc.sendPluginResult(pluginResult);
                }
            } 
        }
    }
    
    if(content == "schedule") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                cJSON* pJson = cJSON_CreateObject();
                fireEvent("add", result, pJson);
                cJSON_Delete(pJson);
                m_cbc.success(result);
            } 
        }
    }
    
    if(content == "update") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                cJSON* pJson = cJSON_CreateObject();
                fireEvent("update", result, pJson);
                cJSON_Delete(pJson);
                m_cbc.success(result);
            } 
        }
    }
    
    if(content == "cancel") {
        m_cbc.success();
    }
    
    if(content == "cancelAll") {
       m_cbc.success();
    }
    
    if(content == "type") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                m_cbc.success(result);
            } 
        }
    }
    
    if(content == "ids") {
        if(json != NULL && json->type == cJSON_Array) {
            m_cbc.success(json);
        }
    }
    
    if(content == "notification") {
        if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                cJSON* pJson = cJSON_Parse(result.c_str());
                if(pJson != nullptr) {
                    m_cbc.success(pJson);
                    cJSON_Delete(pJson);
                } else {
                    m_cbc.success();
                }
            } 
        }
    }
    
    if(content == "notifications") {
        if(json != NULL && json->type == cJSON_Array) {
            cJSON* pArrayJson = cJSON_CreateArray();
            int count = cJSON_GetArraySize(json);
            for(int i=0; i<count; i++) {
                string result = cJSON_GetArrayItem(json, i)->valuestring;
                cJSON* pJson = cJSON_Parse(result.c_str());
                cJSON_AddItemToArray(pArrayJson,pJson);
            }
            m_cbc.success(pArrayJson);
            cJSON_Delete(pArrayJson);
        }
    }
    
    if(content == "openNotificationSettings") {
         if(json != NULL && json->type == cJSON_Array) {
            int count = cJSON_GetArraySize(json);
            if(count > 0) {
                string result = cJSON_GetArrayItem(json, 0)->valuestring;
                if(result == "true") {
                    m_cbc.success();
                } else {
                    m_cbc.error(result);
                }
            } 
        }
    }
    return true;
}